import re
import os
import string
import redis
import random
import json
from p6_0518 import settings
from .tasks import send_message
from captcha.image import ImageCaptcha
from django.http import HttpResponse
from django.shortcuts import render
from rest_framework.generics import GenericAPIView
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.mixins import *
from rest_framework.generics import ListCreateAPIView,RetrieveUpdateDestroyAPIView
from users.serializer import *
from users.models import *
from rest_framework.viewsets import ModelViewSet
from django.contrib.auth.hashers import check_password
from django.contrib.auth import authenticate
from rest_framework_jwt.utils import jwt_payload_handler,jwt_encode_handler
from datetime import datetime
import time
from django.db import models
from rest_framework.pagination import PageNumberPagination


# 部门
class DepartmentView(ListCreateAPIView):
    queryset = Department.objects.all()
    parser_classes = DepartmentModelSer

    # 查看所有
    # def get(self,request,*args,**kwargs):
        # deps = self.get_queryset()
        # deps_ser = self.get_serializer(deps,many=True)
        # return Response(deps_ser.data)
        # return self.list(request,*args,**kwargs)

    # 添加
    # def post(self,request):
        # name = request.data.get('name')
        # dep = Department.objects.filter(name=name)
        # if dep:
        #     return Response({'code':400,'msg':'部门已经存在'})
        # # 实例化一个序列化器对象
        # ser = self.get_serializer(data=request.data)
        # # 数据校验
        # if ser.is_valid():
        #     ser.save()
        #     return Response({'code':200,'msg':'添加成功'})
        # else:
        #     return Response({'error':ser.errors,'code':400})
        # return self.list(request)

class DepartmentInfoView(RetrieveUpdateDestroyAPIView):
    queryset = Department.objects.all()
    serializer_class = DepartmentModelSer
    lookup_field = 'pk'
    lookup_url_kwarg = 'pk'

    # 查看一个
    # def get(self,requeat,pk):
    #     try:
    #         dep = self.get_object()
    #         dep_ser = self.get_serializer(dep)
    #         return Response(dep_ser.data)
    #     except:
    #         return self.retrieve(requeat,pk)

    # 更新一个
    # def put(self,request,pk):
        # dep = Department.objects.filter(id=pk).first()
        # ser = DepartmentSer(instance=dep,data=request.data)
        # # 数据校验
        # ser.is_valid(raise_exception=True)
        # ser.save()
        # return Response({'code':200,'msg':'更新成功'})
        # return self.update(request,pk)

    # 删除一个
    # def delete(self,request,pk):
        # dep = Department.objects.filter(id=pk).first()
        # dep.delete()
        # return Response({'code':200,'msg':'删除成功'})
        # return self.destroy(request,pk)

# 员工
class StaffView(ModelViewSet):
    queryset = Staff.objects.all()
    serializer_class = StaffSer

# 职责表
class DutyAPIView(ModelViewSet):
    queryset = Duty.objects.all()
    serializer_class = DutySer


# 发送短信的视图
class SmsAPIView(APIView):
    def get(self,request):
        """
        1. 前端要传一个手机号
        2.后端接收手机号, 判断手机号的合法性（简单判断是否长度为十一位）
        3.手机号不合法的时候直接返回响应
        4.手机号合法，判断用户是否在一分钟之内多次获取短信验证码
           是：返回响应 “获取验证码过于频繁” flag
           否：生成随机验证码，存入redis 请求容联云给发当前的手机号发送短信

        5. 判断容联云是否发送成功
           是：响应给用户 发送短信成功
           否：          发送短信失败
        """
        # 1.前端传一个手机号
        mobile = request.GET.get('mobile')
        
        # 2.判断手机号的合法性（简单判断是否长度为十一位
        if mobile and len(mobile) == 11:
            # 4.手机号合法，判断用户是否在一分钟之内多次获取短信验证码
            # 是：返回响应 “获取验证码过于频繁” flag
            # 否：生成随机验证码，存入redis 请求容联云给发当前的手机号发送短信
            redis_conn = redis.Redis()
            flag_key = "%s_flag"%mobile
            # sms_key = "%s_sms"%mobile
            if redis_conn.get(flag_key):
                # 说明是一分钟之内的操作
                return Response({"code":200,"msg":"发送短信验证码过于频繁"})
            else:
                # 说明是一分钟后再次请求
                # 生成随机验证码并存入redis
                sms_code = random.randint(1000,9999)
                redis_conn.set(mobile,sms_code,ex=300)
                # 存储flag 标识 是否操作频繁
                redis_conn.set(flag_key,1,ex=60)
                # 请求容联云发送短信
                result = send_message(sms_code,mobile, expire=5)
                # 5.
                # 判断容联云是否发送成功
                # 是：响应给用户 发送短信成功
                # 否：          发送短信失败
                if result:
                    return Response({"code":200,"msg":"发送短信成功"})
                return Response({"code":501,"msg":'发送短信失败'})

        else:
            # 3.手机号不合法的时候直接返回响应
            return Response({"code":400,"msg":"手机号不合法"})


    # 校验短信验证码
    # def post(self, request):
    #     # 接收数据
    #     mobile = request.data.get("mobile")
    #     sms_code = request.data.get("sms_code")
    #
    #     # 连接redis
    #     redis_conn = redis.Redis()
    #     sms_key = "%s_sms" % mobile
    #     print(sms_key)
    #
    #     # 获取redis里面存储的短信验证码
    #     stored_sms = redis_conn.get(sms_key)
    #     if not stored_sms:
    #         return Response({"code": 200, "msg": "验证码已过期"})
    #
    #     # 对比验证码是否一致
    #     if stored_sms.decode() == sms_code:
    #         return Response({"code": 200, "msg": "验证码对比成功"})
    #
    #     else:
    #         return Response({"code": 400, "msg": "验证码不一致"})

# 登录
class LoginAPIView(APIView):
    def post(self,request):
        # 1.获取前端传入的数据
        username = request.data.get('username')
        password = request.data.get('password')
        mobile = request.data.get('mobile')
        sms_code = request.data.get('smsCode')

        # 2.判断是否是第一次登录
            # 是 实现注册的功能 验证码验证
            # 否 已经账号 优先使用密码认证
                # 密码错误，检测是否有短信验证码有 重置密码无 密码输入错误 返回响应
                # 密码正确 判断是否有管理员权限 有成功登录 无提示无权限

        # 查询用户 判断是否是第一次登录
        user = User.objects.filter(username=username).first()
        redis_conn = redis.Redis(host="localhost",port=6379)
        if user:
            # 说明是后续的登录 有限使用密码验证

            # user_valid = authenticate(username=username,password=password)

            # 对认证的结果进行判断
            if check_password(password, user.password):
                # 密码正确 & is_staff = True is_active = True

                # 登录成功 需要保持会话保持 jwt token
                token = self.gen_token(user)
                user.last_login = datetime.now()
                user.save()

                # # 获取当前用户所有的权限 并存入redis
                # roles = user.role.all()
                # permissions_list = []
                # for role in roles:
                #     # 根据角色查询所有权限
                #     role_permissions = role.Permission_set.all().values_list('code_name')
                #     permissions_list += [i[0] for i in role_permissions]
                #
                # # 权限去重
                # permissions_list = list(set(permissions_list))
                #
                # # 保存
                # key = 'user_permission_%s'%user.id
                # redis_conn.set(key,json.dumps(permissions_list))

                return Response({
                    'code':200,
                    'msg':'登录成功，进入首页',
                    'data':{
                        'username':user.username,
                        'user_id':user.id,
                        'token':token
                    }
                })

            else:
                # 密码错误|不是管理员|账号未激活
                # if user.is_staff and user.is_active:
                if mobile and sms_code:
                    # if sms_code:
                        # 用户重置密码

                        sms_code_valide = self.validate_sms_code(redis_conn,mobile,sms_code)
                        if sms_code_valide:
                            # 重置密码
                            user.set_password(password)
                            user.save()
                            return Response({'code':207,'msg':'密码已经重置'})
                        else:
                            return Response({'code':204,'msg':'验证码过期或错误'})
                else:
                    return Response({'code':205,'msg':'用户名或密码错误'})

        else:
            # 说明用户是第一次登录 使用短信验证码注册
            if not sms_code:
                return Response({'code':208,'msg':'需要手机注册'})

            redis_conn = redis.Redis()
            sms_code_valide = self.validate_sms_code(redis_conn,mobile,sms_code)
            # 判断验证结果
            if sms_code_valide:
                # 注册用户信息
                user = User.objects.create_user(username=username,password=password,mobile=mobile,last_login=datetime.now())
                user.save()
                # 此时 is_staff(False) is_active(True)
                return Response({'code':201,'msg':'注册成功，需申请管理员权限'})
            else:
                # 验证码过期或错误
                return Response({'code':204,'msg':'验证码过期或错误'})




        # return Response({'code':200,'msg':'登陆成功'})

    @staticmethod
    def validate_sms_code(conn,mobile,sms_code):
        # 构造key
        # sms_key = '$s_sms'%mobile
        # 获取redis的验证码
        stored_sms = conn.get(mobile)
        # if not stored_sms:
        #     return False
        # 对比验证码是否一致
        if stored_sms.decode() == sms_code:
            return True
        else:
            return False

    @staticmethod
    def gen_token(user):
        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)
        return token

# 统计用户总量
class UserTotalCount(APIView):
    def get(self,rquest):
        # 查询用户并统计
        num = User.objects.all().count()
        return Response({'code':200,'total_count':num})

# 日增用户数量
class UserDayIncrement(APIView):
    def get(self,request):
        # 获取今日的时间
        n_time = time.strftime('%Y-%m-%d')
        # 查询日增的用户并统计数量
        num = User.objects.filter(date_joined__contains=n_time).count()
        # 返回响应
        return Response({'count':num})

# 统计日活用户
class UserDayLive(APIView):
    def get(self,request):
        # 获取当前时间
        n_time = time.strftime("%Y-%m-%d")
        # 根据当前时间过滤用户，获取用户数量
        num = User.objects.filter(last_login__contains=n_time).count()
        # 返回
        return Response({"count": num})

class MyPagination(PageNumberPagination):
    page_size = 4
    max_page_size = 20
    page_size_query_param = 'pageSize'
    page_query_param = 'page'

# 用户信息
class UserInfoViewSet(ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSer
    lookup_field = 'pk'
    lookup_url_kwarg = 'pk'

    def create(self, request, *args, **kwargs):
        # 获取前端传入的数据
        username = request.data.get('username')
        password = request.data.get('password')
        mobile = request.data.get('mobile')
        email = request.data.get('email')

        # 检验
        if not all([username,password]):
            return Response({'code':400,'msg':'用户名和密码不能为空'})

        # 正则验证数据
        if not re.findall(r'^\w{5,20}$',username):
            return Response({'code':400,'msg':'用户名是5到20位数字字母或下划线'})

        if not re.findall(r'^[\w!@#$%^&*]{8,20}$',password):
            return Response({'code':400,'msg':'密码是8到20位数字、字母或下划线以及特殊!@#$%^&*符号'})

        if mobile:
            if not re.findall(r'1[34578]\d{9}$',mobile):
                return Response({'code':400,'msg':'手机号不符合要求'})

        # 去重(username,mobile)
        user = User.objects.filter(models.Q(username=username)|models.Q(password=password))
        if user:
            return Response({'code':400,'msg':'用户名或手机号重复'})

        # 存储用户数据-创建用户
        User.objects.create_user(username=username,password=password,mobile=mobile,email=email,last_login=datetime.now())
        return Response({"code":200,'msg':'添加用户成功'})

# 上传头像
class Headers(APIView):
    def post(self,request):
        print('上传的头像数据',request.data)
        # 前端获取数据
        token = request.data.get('token')
        file = request.data.get('file')
        # 验证token
        try:
            payload = jwt_encode_handler(token)
        except:
            return Response({"code":400,'msg':'未认证'})
        file_name = file.name
        static_path = 'static/images/users'
        file_path = os.path.join(settings.BASE_DIR,static_path)
        if not os.path.exists(file_path):
            os.makedirs(file_path)
        ful_path = os.path.join(file_path,file_name)

        with open(ful_path,'wb')as f:
            f.write(file.file.read())
        return Response({'code':200,'msg':'上传图片成功','static_path':static_path})

# 头像图片
class HeadImg(ModelViewSet):
    queryset = Head.objects.all()
    serializer_class = HeadSer
    lookup_field = 'pk'
    lookup_url_kwarg = 'pk'
    # 重写create方法
    def create(self, request, *args, **kwargs):
        # 接收前端数据
        head_id = request.data.get('head')
        image = request.data.get('image')
        # 获取头像
        result = Head.objects.filter(head_id=head_id,image=image)
        if request:
            return Response({'code':400,'msg':'商品已经存在'})
        Head.objects.create(head_id=head_id,image=image)
        return Response({'code':200,'msg':'图片添加成功'})

# 权限视图
class PermissionViewSet(ModelViewSet):
    queryset = Permission.objects.all()  # 查询集
    serializer_class = PermissionSer
    lookup_field = 'pk'
    lookup_url_kwarg = 'pk'

# 角色的视图
class RoleViewSet(ModelViewSet):
    queryset = PermissionType.objects.all()
    serializer_class = PermissionTypeSer
    lookup_field = 'pk'
    lookup_url_kwarg = 'pk'































































